const Hook = require('./hook');

class HookCodeFactory {
    constructor() {
        this.options = undefined;
    }
    
    setup(instance, options) {
        // 遍历出 tap 中定义过的 function
        instance._x = options.taps.map(t => t.fn);
    }

    create(options) {
        this.options = options;
        
        let fn;
        switch (this.options.type) {
            case "sync":
                fn = new Function(
                    this.args,
                    this.content(options)
                );
                break;
            // ...
        }
        return fn;
    }

    getTapFn(idx) {
        return `this._x[${idx}]`; 
    }

    callTap(tapIndex) {
        let code = "";
        code += `var _fn${tapIndex} = ${this.getTapFn(tapIndex)};\n`;
        code += `_fn${tapIndex}(${this.args});\n`
        return code;
    }

    callTapsSeries() {
        let code = '';
        for(let j = 0; j < this.options.taps.length; j++) {
            const content = this.callTap(j);
            code += content;
        }
        return code;
    }
}

class SyncHookCodeFactory extends HookCodeFactory {
    content() {
        return this.callTapsSeries();
    }
}

const factory = new SyncHookCodeFactory();

const COMPILE = function (options) {
    factory.setup(this, options);    // 订阅事件
    return factory.create(options);    // 动态生成 call 方法
};

function SyncHook(args = [], name = undefined) {
    const hook = new Hook(args, name);
    hook.constructor = SyncHook;
    hook.compile = COMPILE;
    return hook;
}

module.exports = SyncHook;